/* 策略模式 */

pub trait TravelStrategy {
    fn travel(&self);
}

pub struct AirPlaneStrategy {}

impl TravelStrategy for AirPlaneStrategy {
    fn travel(&self) {
        println!("乘坐飞机");
    }
}

pub struct TrainStrategy {}

impl TravelStrategy for TrainStrategy {
    fn travel(&self) {
        println!("乘坐火车");
    }
}

pub struct BicycleStrategy {}

impl TravelStrategy for BicycleStrategy {
    fn travel(&self) {
        println!("骑自行车");
    }
}

pub struct PersonContext {
    travelStrategy: Box<dyn TravelStrategy>
}

impl PersonContext {
    fn travel(&self) {
        self.travelStrategy.travel();
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_strategy_1() {
        let travel = TrainStrategy{};
        let person = PersonContext {
            travelStrategy: Box::new(travel)
        };
        person.travel();
    }

    #[test]
    fn test_strategy_2() {
        let airplane = AirPlaneStrategy{};
        let train = TrainStrategy{};
        let bicycle = BicycleStrategy{};

        let mut person = PersonContext {
            travelStrategy: Box::new(airplane)
        };
        println!("第一段旅程");
        person.travel();

        println!("第二段旅程");
        person.travelStrategy = Box::new(train);
        person.travel();

        println!("第三段旅程");
        person.travelStrategy = Box::new(bicycle);
        person.travel();
    }
}